<?php
require_once('includes/clases/Horario.php');
require_once('includes/clases/Grupo.php');
require_once('includes/clases/ConstantesCargaAcademica.php');
require_once('includes/clases/Logger.php');
require_once('includes/clases/AccesoDatosCargaAcademica.php');
require_once('includes/clases/ManejoArchivoCargaAcademica.php');
require_once('includes/clases/HorarioProfesor.php');

class ProcesoCargaAcademica{
	private $logger = null;
    private $accesoDatos = null;
    private $manejoArchivo = null;

	function __construct() {
		$this->logger = new Logger();
        $this->accesoDatos = new AccesoDatosCargaAcademica( $this->logger );
        $this->manejoArchivo = new ManejoArchivoCargaAcademica( $this->accesoDatos, $this->logger );
	}

    function existeInformacionDelTrimestre( $idTrimestre ){
        $idGrupo = $this->accesoDatos->db_obtener_id_grupo_by_trimestre( $idTrimestre );
        return ( $idGrupo != null );
    }

	function procesar( $idTrimestre, $archivos ){
        $this->logger->apagar();

        $rutaArchivoAProcesar = $this->manejoArchivo->guardar( $archivos );        

        $this->logger->log( "Ruta archivo a procesar: " . $rutaArchivoAProcesar );

        if( !is_null( $rutaArchivoAProcesar ) ){            

            $objPHPExcel = $this->manejoArchivo->leerArchivo( $rutaArchivoAProcesar );

            if( !( $objPHPExcel == null ) ){          

                $this->crearObjetosHorarioYGrupo( $objPHPExcel, $idTrimestre );

                $this->procesarAsignarProfesorAGrupo( $idTrimestre );

            }

        }else{
            $this->logger->log( "Error al guardar el archivo", Logger::$ERROR );
        }

        return $this->logger->logError;
    }

    function procesarAsignarProfesorAGrupo( $idTrimestre ){        
        $grupos = $this->accesoDatos->db_obtener_grupo_by_trimestre( $idTrimestre );
        $this->iterarGrupos( $grupos );
    }

    function iterarGrupos( $grupos ){
        // elimina la informacion de los horarios de la tabla temporal
        $this->accesoDatos->db_eliminar_horario_profesor_temporal();
        // itera todos los grupos
        foreach( $grupos as $grupo ) {            
            // itera cada grupo       
            $grupoAsignado = false;
            // obtiene todos los horarios de todos los profesores que aplican para ese grupo, ordenada por profesor
            $horariosProfesoresGrupo = $this->accesoDatos->db_obtener_horarios_profesores_for_grupo( $grupo->id );
            // cuenta la cantidad de 
            $cantidadHorariosProfesoresGrupo = count( $horariosProfesoresGrupo );
            $horarioProfesor = null;
            $idProfesor = null;
            $temporalHorariosProfesor = null;
            for( $i = 0; $i < $cantidadHorariosProfesoresGrupo; $i++ ){
                $this->resultado( "     iteracion : " . $i . " " );
                $horarioProfesor = $horariosProfesoresGrupo[ $i ];
                // es la primera vez que entra al ciclo y $idProfesor es null
                if( $idProfesor == null ){
                    $idProfesor = $horarioProfesor->profesor;
                    // se crea un arreglo temporal para los horarios de cada profesor asociados a ese grupo
                    $temporalHorariosProfesor = array();
                    $temporalHorariosProfesor[] = $horarioProfesor;
                }else{
                    if( $idProfesor == $horarioProfesor->profesor ){   
                        // agrega el horario del profesor al arreglo temporal
                        $temporalHorariosProfesor[] = $horarioProfesor;
                    }else{                       
                        // al ser distinto el profesor, valida el arreglo temporal de los horarios del profesor con los horarios del grupo
                        if( $this->validarAsignar( $idProfesor, $grupo, $temporalHorariosProfesor ) == true ){
                            $grupoAsignado = true;
                            break;
                        }
                        $i--;
                        $idProfesor = null;
                    }
                }
            }
            if( $grupoAsignado == false ){
                $this->resultado( "     iteracion : " . $i . " " );
                // ejecuta el validar y asignar al ultimo profesor, valida el arreglo temporal de los horarios del profesor con los horarios del grupo
                if( $this->validarAsignar( $idProfesor, $grupo, $temporalHorariosProfesor ) == true ){
                    continue;
                }
            }
            $this->resultado( "No se logro asignar el grupo: " . $grupo->grupo );
        }
    }

    function validarAsignar( $idProfesor, $grupo, $temporalHorariosProfesor ){
        $this->resultado( "--- validarAsignar() ");
        if( $this->validarSiEmpatanHorarios( $grupo, $temporalHorariosProfesor ) == true ){
            // Validar asignaciones anteriores profesor.
            if( $this->tieneAsignacionesAnterioresProfesor( $idProfesor, $grupo->id ) == true ){
                $this->resultado( "- tiene asignacion anterior -" );
                return false;
            }
            // si se empataron los horarios profesor y grupo, se asigna dicho profesor al grupo
            $grupo->profesor = $idProfesor;
            $this->resultado( "Se asigno al grupo: " . $grupo->grupo . " el profesor con identificador: " . $grupo->profesor );
            $this->asignarProfesorAGrupo( $grupo );
            return true;
        }
        return false;
    }

    function tieneAsignacionesAnterioresProfesor( $idProfesor, $idGrupo ){
        $tieneAsignacionAnterior = false;
        $horarios = $this->accesoDatos->db_obtener_horarios_by_grupo( $idGrupo );
        foreach ($horarios as $horario) {
            $resultado = $this->accesoDatos->db_tiene_asignacion_profesor_grupo_temporal_en_horario( $idProfesor, $horario );
            $this->resultado( "--- idProfesor $idProfesor, grupo $idGrupo, dia horario $horario->dia: $resultado" );
            if( $resultado != 0 ){
                $tieneAsignacionAnterior = true;
                break;
            }
        }
        if( $tieneAsignacionAnterior == false ){
            $this->resultado( "NO tieneAsignacionAnterior: " . $tieneAsignacionAnterior );    
        }else{
            $this->resultado( "SI tieneAsignacionAnterior: " . $tieneAsignacionAnterior );
        }
        return $tieneAsignacionAnterior;
    }

    function asignarProfesorAGrupo( $grupo ){
        if( $this->accesoDatos->db_asignar_profesor_a_grupo( $grupo ) == 1 ){
            //$this->resultado( "->->-> Se asigno el grupo ( " . $grupo->id . " ): " . $grupo->grupo . " al profesor " . $grupo->profesor );
        }
        $horarios = $this->accesoDatos->db_obtener_horarios_by_grupo( $grupo->id );
        foreach ($horarios as $horario) {
            //$this->resultado( "* * * horario: ( dia: " . $horario->dia . " -> " . $horario->inicio . " - " . $horario->fin . " )" );
            if( $this->accesoDatos->db_asignar_profesor_grupo_temporal( $grupo, $horario ) == 1 ){
                //$this->logger->log( "->->-> Se asigno el profesor a la tabla temporal, profesor: " . $grupo->profesor , Logger::$ERROR );
            }
        }
    }

    function validarSiEmpatanHorarios( $grupo, $horariosProfesor ){
        //$this->logger->log( " + validarSiEmpatanHorarios: " . count( $horariosProfesor ), Logger::$ERROR );
        $respuesta = false;
        $horarios = $this->accesoDatos->db_obtener_horarios_by_grupo( $grupo->id );
        $cantidadHorarios = count( $horarios );
        $horario = null;
        for( $i = 0; $i < $cantidadHorarios; $i++ ){
            $horario = $horarios[ $i ];
            $empatoHorario = false;
            $horarioProfesor = null;
            $cantidadHorariosProfesor = count( $horariosProfesor );
            for( $j = 0; $j < $cantidadHorariosProfesor; $j++ ){
                $horarioProfesor = $horariosProfesor[ $j ];
                $empatoHorario = $horarioProfesor->inicio <= $horario->inicio && 
                                $horarioProfesor->fin >= $horario->fin && 
                                $horarioProfesor->dia == $horario->dia;
                if( $empatoHorario == true ){
                    break;
                }
            }
            $respuesta = $empatoHorario;
            //$this->logger->log( " => respuesta : " . $respuesta . " del horario: " . $horario->inicio . " - " . $horario->fin . " - " . $horario->dia, Logger::$ERROR );
            if( $empatoHorario == false ){
                break;
            }
        }
        return $respuesta;
    }   

    function crearObjetosHorarioYGrupo( $objPHPExcel, $idTrimestre ){
        if( $objPHPExcel == null || is_null($objPHPExcel) || $idTrimestre == null ){
            $this->logger->log( "Error al crear horarios y grupos.", Logger::$ERROR );
            return;
        }

        $iteradorFila = 2;
        $fila = null;
        $horarios = null;       

        if( $this->existeInformacionDelTrimestre( $idTrimestre ) ){
            $this->logger->log( "Ya existe informacion del trimestre, se sobreescribira.", Logger::$ERROR );
        }

        $horario = null;
        $grupo = null;
        while( $this->manejoArchivo->validaExisteSiguienteFila( $objPHPExcel, $iteradorFila ) ){
            $grupo = $this->manejoArchivo->parsearGrupo( $objPHPExcel, $iteradorFila, $idTrimestre );
            if( $grupo == null ){
            	$iteradorFila++;
            	continue;
            }
            $this->accesoDatos->guardarGrupo( $grupo );
            $this->logger->log( $grupo->display(), Logger::$INFO );
            $horarios = $this->manejoArchivo->parsearHorarios( $objPHPExcel, $iteradorFila, $grupo );
            if( $horarios != null ){
            	$this->logger->log( "borrarHorariosDelGrupo: " . $this->accesoDatos->borrarHorariosDelGrupo( $grupo ), Logger::$INFO );
            	$this->accesoDatos->guardarHorarios( $horarios );
            }
            $iteradorFila++;
        }
    }

    function resultado( $resultado ){
        $this->logger->log( $resultado, Logger::$ERROR );
    }
}
?>